using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.PageFlow.Utils;
using System.Data;
using System.Data.Common;
using WCSFContrib.PageFlow.Xml.Storage.EnterpriseLibrary.Properties;
using System.Collections.Specialized;

namespace WCSFContrib.PageFlow.Xml.Storage.EnterpriseLibrary
{
    public class XmlPageFlowInstanceSqlStore : IXmlPageFlowInstanceStore
    {
        private Database _pageFlowStorage;

        public XmlPageFlowInstanceSqlStore(NameValueCollection configuration)
        {
            Guard.ArgumentNotNull(configuration, "configuration");

            string databaseName = configuration["connectionString"];
            Guard.ArgumentNotNullOrEmptyString(databaseName, "configuration[\"connectionString\"]");

            _pageFlowStorage = DatabaseFactory.CreateDatabase(databaseName);
        }

        public XmlPageFlowInstanceSqlStore(string databaseName)
		{
            Guard.ArgumentNotNullOrEmptyString(databaseName, "databaseName");
            _pageFlowStorage = DatabaseFactory.CreateDatabase(databaseName);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
        public void Add(XmlPageFlowInstance instance)
        {
            Guard.ArgumentNotNull(instance, "instance");

            byte[] binaryState = Util.SerializationHelper.SerializeBinaryArray(instance);
            using (DbCommand command = _pageFlowStorage.GetStoredProcCommand("dbo.pageFlow_InsertInstanceState"))
            {
                _pageFlowStorage.AddInParameter(command, "@instanceID", DbType.Guid, instance.InstanceId);
                _pageFlowStorage.AddInParameter(command, "@binaryState", DbType.Binary, binaryState);
                _pageFlowStorage.ExecuteNonQuery(command);
            }
        }

        public void Remove(Guid instanceId)
        {
            if (instanceId == Guid.Empty)
                throw new ArgumentException(Resources.InstanceIdCannotBeEmpty, "instanceId");

            using (DbCommand command = _pageFlowStorage.GetStoredProcCommand("dbo.pageFlow_RemoveInstanceState"))
            {
                _pageFlowStorage.AddInParameter(command, "@instanceID", DbType.Guid, instanceId);
                _pageFlowStorage.ExecuteNonQuery(command);
            }
        }

        public XmlPageFlowInstance Get(Guid instanceId)
        {
            if (instanceId == Guid.Empty)
                throw new ArgumentException(Resources.InstanceIdCannotBeEmpty, "instanceId");

            using (DbCommand command = _pageFlowStorage.GetStoredProcCommand("dbo.pageFlow_GetInstanceState"))
            {
                _pageFlowStorage.AddInParameter(command, "@instanceID", DbType.Guid, instanceId);
                using (IDataReader reader = _pageFlowStorage.ExecuteReader(command))
                {
                    if (reader.Read())
                    {
                        byte[] arrayInstance = (byte[])reader.GetValue(0);
                        return Util.SerializationHelper.DeserializeBinaryArray<XmlPageFlowInstance>(arrayInstance);
                    }
                }
            }
            return null;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
        public void Update(XmlPageFlowInstance instance)
        {
            Guard.ArgumentNotNull(instance, "instance");

            byte[] binaryState = Util.SerializationHelper.SerializeBinaryArray(instance);
            using (DbCommand command = _pageFlowStorage.GetStoredProcCommand("dbo.pageFlow_UpdateInstanceState"))
            {
                _pageFlowStorage.AddInParameter(command, "@instanceID", DbType.Guid, instance.InstanceId);
                _pageFlowStorage.AddInParameter(command, "@binaryState", DbType.Binary, binaryState);
                _pageFlowStorage.ExecuteNonQuery(command);
            }
        }
    }
}
